﻿#define _CRT_SECURE_NO_WARNINGS

#include<iostream>
using namespace std;

//·析构函数
//析构函数与构造函数功能相反，析构函数不是完成对对象本⾝的销毁，⽐如局部对象是存在栈帧的，
//函数结束栈帧销毁，他就释放了，不需要我们管，C++规定对象在销毁时会⾃动调⽤析构函数，完成对
//象中资源的清理释放⼯作。析构函数的功能类⽐我们之前Stack实现的Destroy功能，⽽像Date没有
//Destroy，其实就是没有资源需要释放，所以严格说Date是不需要析构函数的。

//析构函数的特点
//·析构函数名是在类名前加上字符 ~
//·⽆参数⽆返回值
//·⼀个类只能有⼀个析构函数。若未显式定义，系统会⾃动⽣成默认的析构函数
//·对象⽣命周期结束时，系统会⾃动调⽤析构函数
//·跟构造函数类似，我们不写编译器⾃动⽣成的析构函数对内置类型成员不做处理，⾃定类型成员会调⽤他的析构函数
//·还需要注意的是我们显⽰写析构函数，对于⾃定义类型成员也会调⽤他的析构，也就是说⾃定义类型成员⽆论什么情况都会⾃动调⽤析构函数
//·如果类中没有申请资源时，析构函数可以不写，直接使⽤编译器⽣成的默认析构函数，如Date；如
//果默认⽣成的析构就可以⽤，也就不需要显⽰写析构，如MyQueue；但是有资源申请时，⼀定要
//⾃⼰写析构，否则会造成资源泄漏，如Stack
//·⼀个局部域的多个对象，C++规定后定义的先析构

//例子：

//日期类函数，不需要写析构函数
class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	~Date()
	{
		cout << "~Date" << endl;
	}

private:
	int _year;
	int _month;
	int _day;
};

//栈类函数，需要析构函数
//由于malloc申请了空间，有一个指针指向了堆的空间，函数生命周期结束后，将该空间返回给系统
//此时需要手动释放该空间，否则只会将利用后的空间返回，从而造成内存泄露
typedef int STDataType;

class Stack
{
public:
	Stack(int n = 4)
	{
		_a = (STDataType*)malloc(sizeof(STDataType) * n);
		if (nullptr == _a)
		{
			perror("malloc申请空间失败");
			return;
		}
		_capacity = n;
		_top = 0;
	}
	
	~Stack()
	{
		cout << "~Stack()" << endl;
		free(_a);
		_a = nullptr;
		_top = _capacity = 0;
	}
private:
	STDataType* _a;
	size_t _capacity;
	size_t _top;
};

//内置类型只需要系统自带的析构函数，而自定义类型需要手动设置析构函数
//虽然系统自带够用，但是有资源申请时，需要手动设置析构函数
class Myqueue
{
private:
	Stack _pusht;
	Stack _popst;
};

int main()
{
	Date d;

	Stack st;

	Myqueue mq;

	return 0;
}

